package com.itheima.health.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.itheima.health.mapper.OrderMapper;
import com.itheima.health.pojo.Member;
import com.itheima.health.pojo.Order;
import com.itheima.health.pojo.Setmeal;
import com.itheima.health.service.MemberService;
import com.itheima.health.service.OrderService;
import com.itheima.health.service.OrderSettingService;
import com.itheima.health.service.SetmealService;
import com.itheima.health.utils.date.DateUtils;
import com.itheima.health.utils.redis.RedisUtil;
import com.itheima.health.utils.resources.RedisMessageConstant;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/*
 *       预约:
 *           1.验证码判断
 *           2.是否预约满
 *           3.是否重复预约
 *           4.预约成功,更新多表
 *
 * */
@Service(loadbalance = "roundrobin",timeout = 4000)
@Transactional
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Reference
    private OrderSettingService orderSettingService;

    @Reference
    private MemberService memberService;

    @Reference
    private SetmealService setmealService;

    @Override
    @LcnTransaction
    public Order add(Map map) {
//        try {
//            Thread.sleep(3000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        //1.对验证码进行判断
        //先获取表单验证码
        String code = (String) map.get("validateCode");
        //再获取用户的手机号
        String telephone = (String) map.get("telephone");
        //获取此用户在缓存中的验证码
        String redisCode = RedisUtil.get(RedisMessageConstant.SENDTYPE_ORDER + telephone);

        //判断
        if (StringUtils.isBlank(redisCode)) {
            //如果缓存验证码为空,表示验证码过期
            throw new RuntimeException("验证码过期或不存在");
        }
        if (StringUtils.isBlank(code)) {
            //如果获取表单验证码为空,表示用户没有输入验证码
            throw new RuntimeException("请填写验证码");
        }
        if (!redisCode.equals(code)) {
            //如果用户输入验证码与缓存中不一致,表示出错
            throw new RuntimeException("验证码输入错误");
        }

        //2.验证预约是否已满
        //先获取用户预约日期
        String orderDate = (String) map.get("orderDate");

        //分布式事务锁
        String setmealLock = "orderLock" + orderDate;//上一把订单锁

        try {
            if (RedisUtil.lock(setmealLock)) {

                //睡10毫秒 给数据库添加数据的时间 防止数据库操作还没完成 锁就被释放 新的进程进来
                //Thread.sleep(1000);

                //根据日期调用方法查询数据库,返回查询结果count
                int count = orderSettingService.selectOrdersettingInfoByOrderDate(orderDate);
                //如果查询结果小于0,表示预约人数已满
                if (count <= 0) {
                    throw new RuntimeException("预约人数已满");
                }

        //3.是否重复预约
        //先根据手机号查询会员表是否存在,判断新老用户
        Member member = memberService.findMemberByTelephone(telephone);

        //1.获取套餐id
        String setmealId = (String) map.get("setmealId");
        Integer sId = Integer.valueOf(setmealId);
        Integer mId = 0;
        if (member != null) {
            //是老用户,进一步判断套餐在当天是否重复预约
            //通过三个字段查询,获取三个字段值
            //1.获取套餐id
            sId = Integer.valueOf(setmealId);
            //2.获取用户id
            mId = member.getId();
            //3.获取用户预约日期,上面有String orderDate = (String) map.get("orderDate");
            int orderExist = baseMapper.findOrderBySetmealIdAndOrderDateAndMemberId(sId, mId, orderDate);
            if (orderExist > 0) {
                throw new RuntimeException("请不要在同一天预约同一个套餐");
            }
        } else {
            //2.表示是新用户,更新会员表数据
            member = new Member();
            member.setName((String) map.get("name"));
            member.setSex((String) map.get("sex"));
            member.setIdCard((String) map.get("idCard"));
            member.setPhoneNumber(telephone);
            member.setRegTime(new Date(System.currentTimeMillis()));
            mId = memberService.saveMenber(member);
        }

                //4.可以预约,多表更新
                //1.更新预约表,将预约数加一
                orderSettingService.updateOrdersettingInfoByOrderDate(orderDate);
                //3.更新订单表
                Order order = new Order();
                order.setMemberId(mId);
                order.setOrderDate(DateUtils.parseString2Date(orderDate, "yyyy-MM-dd"));
                order.setOrderType((String) map.get("orderType"));
                order.setSetmealId(sId);
                order.setOrderStatus("未到诊");
                baseMapper.insert(order);
                return order;
            } else {
                throw new RuntimeException("你的网络不好，请稍后再试");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            //不管订单下单成功与否 都释放锁
            RedisUtil.unlock(setmealLock);
        }
    }

    //根据订单号查询  体检人(会员表)  体检套餐(套餐表)     体检日期,预约类型(订单表)
    @Override
    public Map selectOrderInfoByOrderId(Integer id) {
        //先根据订单表的id查询  体检日期,预约类型以及套餐id,会员id
        Order order = baseMapper.selectOrderInfoByOrderId(id);
        //获取订单表的套餐id,根据套餐id查询套餐名
        Integer setmealId = order.getSetmealId();
        Setmeal setmeal = setmealService.findSetmealInfoById(setmealId);
        String setmealName = setmeal.getName();

        //根据订单表的会员id查询会员名
        Integer memberId = order.getMemberId();
        Member member = memberService.findMemberNameByMemberId(memberId);

        HashMap<String, String> map = new HashMap<>();
        map.put("member", member.getName());
        map.put("setmeal", setmealName);
        map.put("orderDate", DateUtils.parseDate2String(order.getOrderDate(),"yyyy-MM-dd"));
        map.put("orderType", order.getOrderType());

        return map;
    }



    //报表数据 todoby dzf
    @Override
    public Integer getDayReservations() {
        return baseMapper.getDayReservations();
    }

    @Override
    public Integer getMonthReservations() {
        return baseMapper.getMonthReservations();
    }

    @Override
    public Integer getWeekReservations() {
        return baseMapper.getWeekReservations();
    }

    @Override
    public Integer getFinishDay() {
        return baseMapper.getFinishDay();
    }

    @Override
    public Integer getFinishWeek() {
        return baseMapper.getFinishWeek();
    }

    @Override
    public Integer getFinishMonth() {
        return baseMapper.getFinishMonth();
    }

    @Override
    public void updateByOrderId(Integer orderId) {
        baseMapper.updateByOrderId(orderId);
    }

    @Override
    public Integer findState(Integer id) {
        return baseMapper.findState(id);

    }

}
